#include "Mutex.h"

namespace Util
{
  Mutex::Mutex()
    : initialOwnership(false)
  {
	  hMutex = CreateMutex(NULL, false, NULL);
  }

  Mutex::Mutex(const char* systemName, bool instantOwnership)
    : initialOwnership(false)
  {
	  hMutex = CreateMutex(NULL, instantOwnership, systemName);
    if(instantOwnership && GetLastError() != ERROR_ALREADY_EXISTS)
      initialOwnership = true;
  }

  Mutex::~Mutex()
  {
	  CloseHandle(hMutex);
  }

  void Mutex::releaseInitialOwnership()
  {
    if(initialOwnership)
    {
      initialOwnership = false;
      ReleaseMutex(hMutex);
    }
  }

  bool Mutex::isInitialOwner()
  {
    return initialOwnership;
  }

  Mutex::Lock::Lock() : target(NULL)
  {
  }

  Mutex::Lock::Lock(Mutex& fresh_target) : target(NULL)
  {
	  lock(fresh_target);
  }

  void Mutex::Lock::lock(Mutex& fresh_target)
  {
	  if(target)
		  release();
	  target = &fresh_target;
    WaitForSingleObject(target->hMutex, INFINITE);
  }

  bool Mutex::Lock::tryLock(Mutex& fresh_target)
  {
    bool locked = WaitForSingleObject(fresh_target.hMutex, 0) != WAIT_TIMEOUT;
	  if(locked)
		  target = &fresh_target;
	  else
		  target = NULL;
	  return locked;
  }

  Mutex::Lock::~Lock()
  {
	  release();
  }

  void Mutex::Lock::release()
  {
	  if(!target)
		  return;
    ReleaseMutex(target->hMutex);
	  target = NULL;
  }
}
